using JEngine.Core;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CL
{
    public class CLEntitySystem
    {
        private readonly Queue<CLEntityRef<CLEntity>>[] queues = new Queue<CLEntityRef<CLEntity>>[CLInstanceQueueIndex.Max];

        public CLEntitySystem()
        {
            for (int i = 0; i < this.queues.Length; i++)
            {
                this.queues[i] = new Queue<CLEntityRef<CLEntity>>();
            }
        }


        public virtual void RegisterSystem(CLEntity component)
        {
          
            Type type = component.GetType();

            CLTypeSystems.CLOneTypeSystems oneTypeSystems = CLEntitySystemSingleton.Instance.TypeSystems.GetOneTypeSystems(type);

            if (oneTypeSystems == null)
            {
                return;
            }

            for (int i = 0; i < oneTypeSystems.QueueFlag.Length; ++i)
            {
                if (!oneTypeSystems.QueueFlag[i])
                {
                    continue;
                }
                this.queues[i].Enqueue(component);
            }
    
        }

        public void Update()
        {
            Queue<CLEntityRef<CLEntity>> queue = this.queues[0];
            int count = queue.Count;
            while (count-- > 0)
            {
                CLEntity component = queue.Dequeue();
                if (component == null)
                {
                  //  CLLog.Warning($"CLEntitySystem component");
                    continue;
                }

                if (component.IsDisposed)
                {

                  //  CLLog.Warning($"CLEntitySystem component IsDisposed:{component.GetType().FullName}");
                    continue;
                }

                if (component is not ICLUpdate)
                {
                   // CLLog.Warning($"CLEntitySystem component is not ICLUpdate :{component.GetType().FullName}");
                    continue;
                }

                try
                {
                    List<CLSystemObject> iUpdateSystems = CLEntitySystemSingleton.Instance.TypeSystems.GetSystems(component.GetType(), typeof(ICLUpdateSystem));
                    if (iUpdateSystems == null)
                    {

                     //   CLLog.Warning($"CLEntitySystem iUpdateSystems null");
                        continue;
                    }

                    queue.Enqueue(component);

                    foreach (ICLUpdateSystem iUpdateSystem in iUpdateSystems)
                    {
                        try
                        {
                            iUpdateSystem.Run(component);
                        }
                        catch (Exception e)
                        {
                            UnityEngine.Debug.LogError(e);
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception($"entity system update fail: {component.GetType().FullName}", e);
                }
            }
        }

        public void LateUpdate()
        {
            Queue<CLEntityRef<CLEntity>> queue = this.queues[1];
            int count = queue.Count;
            while (count-- > 0)
            {
                CLEntity component = queue.Dequeue();
                if (component == null)
                {
                    continue;
                }

                if (component.IsDisposed)
                {
                    continue;
                }

                if (component is not ICLLateUpdate)
                {
                    continue;
                }

                List<CLSystemObject> iLateUpdateSystems = CLEntitySystemSingleton.Instance.TypeSystems.GetSystems(component.GetType(), typeof(ICLLateUpdateSystem));
                if (iLateUpdateSystems == null)
                {
                    continue;
                }

                queue.Enqueue(component);

                foreach (ICLLateUpdateSystem iLateUpdateSystem in iLateUpdateSystems)
                {
                    try
                    {
                        iLateUpdateSystem.Run(component);
                    }
                    catch (Exception e)
                    {
                        UnityEngine.Debug.LogError(e);
                    }
                }
            }
        }
    }
}
